package com.ks.utils.poi;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.VerticalAlign;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

@SuppressWarnings("unused")
public class SUtilWordReplace {
	public static void searchAndReplace(String srcPath, String destPath, Map<String, String> map, Map<String, String> mapImage) {
		try {
			searchAndReplace(srcPath,new FileOutputStream(destPath),map,mapImage);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public static void searchAndReplace(String srcPath, OutputStream outStream, Map<String, String> map, Map<String, String> mapImage) {
		try {
			XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(srcPath));

			// 替换表格占位符
			checkTables(document, map);
			// 替换段落占位符
			checkParagraphs(document, map);
			// 在末尾添加文字
			//addParagraphToWord(document, "这里添加文字", 30, 0, "#EB9074", true);
			// 替换图片
			replaceTextToImage(document, mapImage, 200, 200);

			document.write(outStream);
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(null != outStream){
				try {
					outStream.flush();
					outStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void checkTables(XWPFDocument document, Map<String, String> map) {
		Iterator<XWPFTable> it = document.getTablesIterator();
		while (it.hasNext()) {
			XWPFTable table = it.next();
			int rcount = table.getNumberOfRows();
			for (int i = 0; i < rcount; i++) {
				XWPFTableRow row = table.getRow(i);
				List<XWPFTableCell> cells = row.getTableCells();
				for (XWPFTableCell cell : cells) {
					List<XWPFParagraph> listCell;
					for (Entry<String, String> e : map.entrySet()) {
						listCell = cell.getParagraphs();
						List<XWPFRun> cellRun;
						Map<String, Object> mapAttr = new HashMap<String, Object>();
						for (int j = 0; j < listCell.size(); j++) {
							if(listCell.get(j).getText().equals(e.getKey())){
								cellRun  = listCell.get(0).getRuns();
								if(cellRun.size() == 0){
									System.out.println("1");
									continue;
								}
								String value = map.get(e.getKey());
								if (null != value) {
									mapAttr = getWordXWPFRunStyle(cellRun.get(0));
									listCell.get(j).removeRun(0);
									XWPFRun newRun = listCell.get(j).insertNewRun(0);
									setWordXWPFRunStyle(newRun, mapAttr, value, false);
									for(int c=1;c<cellRun.size();c++){
										listCell.get(j).removeRun(c);
										newRun = listCell.get(j).insertNewRun(c);
										setWordXWPFRunStyle(newRun, mapAttr, "", false);
									}
								}
								
							}else if (listCell.get(j).getText().indexOf(e.getKey()) != -1) {
								StringBuilder keyBuffer = new StringBuilder();
								cellRun = listCell.get(j).getRuns();
								
								boolean isAppend = false;
								for (int c = 0; c < cellRun.size(); c++) {
									String key = cellRun.get(c).getText(0).trim().replaceAll("[\\t\\n\\r]", "");
									if(key.startsWith("$")){
										keyBuffer.delete(0, keyBuffer.length());
										keyBuffer.append(key);
										if(!key.endsWith("}")){
											isAppend = true;
										}
									}else if(key.endsWith("}")){
										keyBuffer.append(key);
										isAppend = false;
									}else{
										if(isAppend){
											keyBuffer.append(key);
										}else{
											keyBuffer.delete(0, keyBuffer.length());
										}
									}
									System.out.println("原始:"+cellRun.get(c).getText(0).trim()+",处理后:"+keyBuffer.toString());
									String value = map.get(key);
									if (null != value) {
										mapAttr = getWordXWPFRunStyle(cellRun.get(c));
										listCell.get(j).removeRun(c);
										XWPFRun newRun = listCell.get(j).insertNewRun(c);
										setWordXWPFRunStyle(newRun, mapAttr, value, false);
									} else if (c == cellRun.size() - 1 && value == null) {
										String a = cellRun.toString().replace(",", "").replace(" ", "").replace("]", "");
										a = a.substring(a.indexOf("$"),a.length());
										value = map.get(a);
										mapAttr = getWordXWPFRunStyle(cellRun.get(0));
										listCell.get(j).removeRun(0);
										XWPFRun newRun = listCell.get(j).insertNewRun(0);
										setWordXWPFRunStyle(newRun, mapAttr, value, false);
										for(c=1;c<cellRun.size();c++){
											listCell.get(j).removeRun(c);
											newRun = listCell.get(j).insertNewRun(c);
											setWordXWPFRunStyle(newRun, mapAttr, "", false);
										}
										
									}
								}
							}
						}
					}
				}
			}
		}
	}

	public static void checkParagraphs(XWPFDocument document, Map<String, String> map) {
		List<XWPFRun> listRun;
		Map<String, Object> mapAttr = new HashMap<String, Object>();
		List<XWPFParagraph> listParagraphs = document.getParagraphs();
		for (int sa = 0; sa < listParagraphs.size(); sa++) {
			//String wordLine = listParagraphs.get(sa).getText();
			//System.out.println(wordLine);
			for (Entry<String, String> e : map.entrySet()) {
				String wordLine = listParagraphs.get(sa).getText();
				if(wordLine.equals(e.getKey())){
					listRun = listParagraphs.get(sa).getRuns();
					String value = map.get(e.getKey());
					if (null != value) {
						// 得到占位符的文本格式
						XWPFRun runOld = listParagraphs.get(sa).getRuns().get(0);
						mapAttr = getWordXWPFRunStyle(runOld); // 封装该占位符文本样式到map
						listParagraphs.get(sa).removeRun(0);// 移除占位符
						// 创建设置对应占位符的文本
						XWPFRun runNew = listParagraphs.get(sa).insertNewRun(0);
						setWordXWPFRunStyle(runNew, mapAttr,value, true);
						for(int c=1;c<listRun.size();c++){
							listParagraphs.get(sa).removeRun(c);// 移除占位符
							runNew = listParagraphs.get(sa).insertNewRun(c);
							setWordXWPFRunStyle(runNew, mapAttr,"", true);
						}
					}
				}else if (wordLine.indexOf(e.getKey()) != -1) {
					listRun = listParagraphs.get(sa).getRuns();
					StringBuilder keyBuffer = new StringBuilder();
					boolean isAppend = false;
					for (int p = 0; p < listRun.size(); p++) {
						//System.out.println(listRun.get(p).toString().trim());
						String key = listRun.get(p).toString().trim().replaceAll("[\\t\\n\\r]", "");
						if(key.startsWith("$")){
							keyBuffer.delete(0, keyBuffer.length());
							keyBuffer.append(key);
							if(!key.endsWith("}")){
								isAppend = true;
							}
						}else if(key.endsWith("}")){
							isAppend = false;
							keyBuffer.append(key);
						}else{
							if(isAppend){
								keyBuffer.append(key);
							}else{
								keyBuffer.delete(0, keyBuffer.length());
							}
						}
						
						System.out.println("原始:"+listRun.get(p).toString().trim()+",处理后:"+keyBuffer.toString());
						String value = map.get(key);
						if (null != value) {
							// 得到占位符的文本格式
							XWPFRun runOld = listParagraphs.get(sa).getRuns().get(p);
							mapAttr = getWordXWPFRunStyle(runOld); // 封装该占位符文本样式到map
							listParagraphs.get(sa).removeRun(p);// 移除占位符
							// 创建设置对应占位符的文本
							XWPFRun runNew = listParagraphs.get(sa).insertNewRun(p);
							setWordXWPFRunStyle(runNew, mapAttr,value, true);
						}
					}
				}
			}
		}
	}

	public static Map<String, Object> getWordXWPFRunStyle(XWPFRun runOld) {
		Map<String, Object> mapAttr = new HashMap<String, Object>();
		mapAttr.put("Color", runOld.getColor());
		if (-1 == runOld.getFontSize()) {
			mapAttr.put("FontSize", 12);
		} else {
			mapAttr.put("FontSize", runOld.getFontSize());
		}
		mapAttr.put("Subscript", runOld.getSubscript());
		mapAttr.put("Underline", runOld.getUnderline());
		mapAttr.put("FontFamily", runOld.getFontFamily());
		return mapAttr;
	}

	public static XWPFRun setWordXWPFRunStyle(XWPFRun runNew, Map<String,Object> mapAttr, String text, boolean flag) {
		runNew.setColor((String) mapAttr.get("Color"));
		if ("-1".equals(mapAttr.get("FontSize").toString())) {// 处理小四字号读取为-1的问题
			runNew.setFontSize(12);
		} else {
			runNew.setFontSize((Integer) mapAttr.get("FontSize"));
		}
		runNew.setBold(flag);
		runNew.setUnderline((UnderlinePatterns) mapAttr.get("Underline"));
		runNew.setText(text);
		runNew.setSubscript((VerticalAlign) mapAttr.get("Subscript"));
		runNew.setFontFamily((String) mapAttr.get("FontFamily"));
		return runNew;
	}

	public static void updatePicture(XWPFDocument document, int id, int width, int height) {
		if (id == 0) {
			id = document.getAllPictures().size() - 1;
		}
		final int EMU = 9525;
		width *= EMU;
		height *= EMU;
		String blipId = document.getAllPictures().get(id).getPackageRelationship().getId();
		CTInline inline = document.createParagraph().createRun().getCTR().addNewDrawing().addNewInline();

		String picXml = "" + "" + "   " + "      " + "         " + id + "\" name=\"Generated\"/>" + "            " + "         " + "         " + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" + "            " + "               " + "            " + "         " + "         " + "            " + "               " + width + "\" cy=\"" + height + "\"/>" + "            " + "            " + "               " + "            " + "         " + "      " + "   " + "";
		// CTGraphicalObjectData graphicData =
		inline.addNewGraphic().addNewGraphicData();
		XmlToken xmlToken = null;
		try {
			xmlToken = XmlToken.Factory.parse(picXml);
		} catch (XmlException xe) {
			xe.printStackTrace();
		}
		inline.set(xmlToken);
		// graphicData.set(xmlToken);
		inline.setDistT(0);
		inline.setDistB(0);
		inline.setDistL(0);
		inline.setDistR(0);
		CTPositiveSize2D extent = inline.addNewExtent();
		extent.setCx(width);
		extent.setCy(height);
		CTNonVisualDrawingProps docPr = inline.addNewDocPr();
		docPr.setId(id);
		docPr.setName("IMG_" + id);
		docPr.setDescr("IMG_" + id);
	}

	public static void addPictureToWord(XWPFDocument document, String imagePath, int imageType, int width, int height) {
		if (0 == imageType) {
			imageType = XWPFDocument.PICTURE_TYPE_JPEG;
		}
		try {
			String ind = document.addPictureData(new FileInputStream(imagePath), imageType);
		} catch (InvalidFormatException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		updatePicture(document, document.getAllPictures().size() - 1, 400, 400);
	}

	public static void addParagraphToWord(XWPFDocument document, String text, int fontSize, int alignment, String RGBColor, boolean isBold) {
		XWPFParagraph paragraph = document.createParagraph();
		if (1 == alignment) {
			paragraph.setAlignment(ParagraphAlignment.CENTER);
		} else if (2 == alignment) {
			paragraph.setAlignment(ParagraphAlignment.CENTER);
		} else if (3 == alignment) {
			paragraph.setAlignment(ParagraphAlignment.RIGHT);
		} else {
			paragraph.setIndentationLeft(alignment);
		}
		XWPFRun runOne = paragraph.createRun();
		runOne.setText(text);
		runOne.setBold(isBold);
		runOne.setFontSize(fontSize);
		if (RGBColor.startsWith("#")) {
			runOne.setColor(RGBColor.substring(1));
		} else {
			runOne.setColor(RGBColor);
		}
	}

	public static void addRunToParagraph(XWPFParagraph paragraph, String text, int fontSize, String RGBColor, boolean isBold, boolean isWrap) {
		XWPFRun runText = paragraph.createRun();
		// runText.setStrike(true); //删除线
		runText.setBold(isBold);
		runText.setColor(RGBColor);
		runText.setFontSize(fontSize);
		runText.setText(text);
		if (isWrap)
			runText.addBreak();
	}

	public static void replaceTextToImage(XWPFDocument document, Map<String,String> mapImage, int width, int height) {
		List<XWPFRun> listRun;
		List<XWPFParagraph> listParagraphs = document.getParagraphs();
		for (int sa = 0; sa < listParagraphs.size(); sa++) {
			for (Entry<String,String> e : mapImage.entrySet()) {
				if (listParagraphs.get(sa).getText().indexOf(e.getKey()) != -1) {
					listRun = listParagraphs.get(sa).getRuns();
					for (int p = 0; p < listRun.size(); p++) {
						if (listRun.get(p).toString().equals(e.getKey())) {
							listParagraphs.get(sa).removeRun(p);// 移除占位符
							// 获得当前CTInline
							CTInline inline = listParagraphs.get(sa).createRun().getCTR().addNewDrawing().addNewInline();
							try {
								insertPicture(document, e.getValue(), inline, width, height);
							} catch (InvalidFormatException e1) {
								e1.printStackTrace();
							} catch (FileNotFoundException e1) {
								e1.printStackTrace();
							}
						}
					}
				}
			}
		}
	}

	public static void insertPicture(XWPFDocument document,String filePath,CTInline inline,int width, int height) throws InvalidFormatException, FileNotFoundException{
             String ind = document.addPictureData(new FileInputStream(filePath), 5);
             int id = document.getAllPictures().size()-1;
             final int EMU = 9525;
             width *= EMU;
             height *= EMU;
             String blipId = document.getAllPictures().get(id).getPackageRelationship()
                     .getId();
             String picXml = ""
                     + ""
                     + "   "
                     + "      "
                     + "         "
                     + id
                     + "\" name=\"Generated\"/>"
                     + "            "
                     + "         "
                     + "         "
                     + blipId
                     + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
                     + "            "
                     + "               "
                     + "            "
                     + "         "
                     + "         "
                     + "            "
                     + "               "
                     + width
                     + "\" cy=\""
                     + height
                     + "\"/>"
                     + "            "
                     + "            "
                     + "               "
                     + "            "
                     + "         "
                     + "      "
                     + "   " + "";
             inline.addNewGraphic().addNewGraphicData();
             XmlToken xmlToken = null;
             try {
                 xmlToken = XmlToken.Factory.parse(picXml);
             } catch (XmlException xe) {
                 xe.printStackTrace();
             }
             inline.set(xmlToken);
             inline.setDistT(0);
             inline.setDistB(0);
             inline.setDistL(0);
             inline.setDistR(0);
             CTPositiveSize2D extent = inline.addNewExtent();
             extent.setCx(width);
             extent.setCy(height);
             CTNonVisualDrawingProps docPr = inline.addNewDocPr();
             docPr.setId(id);
             docPr.setName("IMG_" + id);
             docPr.setDescr("IMG_" + id);
     }
	
	public static String getBase64(String path){
		FileInputStream in =  null;
		String result = null;
		try {
			in = new FileInputStream(path);
			byte[] buffers = new byte[(int)in.available()];
			in.read(buffers);
			result = Base64Utils.getBASE64(buffers);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(null != in){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}
	
	 public static void main(String[] args) {
         HashMap<String,String> map = new HashMap<String,String>();
         HashMap<String,String> mapImage = new HashMap<String,String>();
         map.put("${area}", "瑞安");
         map.put("${teacher}", "的发生的");
         map.put("${idcard}", "3303811987007071855");
         map.put("${school}", "的法萨芬的萨芬士大夫撒旦丰盛的");
         map.put("${videoname}", "的弗拉绝色赌妃静安寺东方巨大搜房撒娇的");
         map.put("${grade}", "高中");
         map.put("${subject}", "信息急速(3-4年级)");
         map.put("${time}", "120");
         map.put("${stel}", "256719");
         map.put("${tel}", "158696496365 158696496363");
         map.put("${about1}", "参与1");
         map.put("${about2}", "参与2");
         map.put("${abouttel1}", "158696496365");
         map.put("${abouttel2}", "158696496365");
         map.put("${intro}", "爱的色放激动撒福建省到房间阿萨德佛方收到放假啊山东发撒的积分 道德经司法噢的萨芬的发撒的发撒的飞阿斯蒂芬十大");
         map.put("${design}", "的发生的发生的饭卡撒的发撒的");
         map.put("${featured}", "的飞洒房间的搜房家撒东方");
         boolean isshare = true;
         boolean ispu = false;
         if(isshare){
        	 map.put("${share}", "同意");
         }else{
        	 map.put("${share}", "不同意");
         }
         if(ispu){
        	 map.put("${public}", "同意");
         }else{
        	 map.put("${public}", "不同意");
         }
         //map.put("${image1}", getBase64("e:\\template\\A.jpg"));
         String srcPath = "e:\\template\\MatchCourseTemplate.docx";
         String destPath = "e:\\template\\输出模版.docx";
         searchAndReplace(srcPath, destPath, map,mapImage);
     }
}
